package com.steve.summary.saga.编制式.coordinator;

import com.steve.summary.saga.编制式.domain.SagaException;
import com.steve.summary.saga.编制式.domain.SagaStatus;
import com.steve.summary.saga.编制式.domain.SagaStep;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @Author: STEVE
 * @Description: SAGA协调器，负责协调SAGA事务的执行和补偿
 * @since: 2025-05-30
 */
public class Saga {

    // SAGA事务ID
    private String sagaId;
    // 所有步骤
    private List<SagaStep> steps = new ArrayList<>();
    // 已执行步骤
    private List<SagaStep> executedSteps = new ArrayList<>();
    // 当前状态
    private SagaStatus status = SagaStatus.STARTED;

    public Saga(String sagaId) {
        this.sagaId = sagaId;
    }

    /**
     * 添加一个SAGA操作
     *
     * @param stepName     步骤名称
     * @param action       正向操作
     * @param compensation 补偿操作
     */
    public void addStep(String stepName, Runnable action, Runnable compensation) {
        steps.add(new SagaStep(stepName, action, compensation));
    }

    /**
     * 执行SAGA事务
     * 按顺序执行所有步骤，如果任何步骤失败则执行补偿
     */
    public void execute() {
        try {
            for (SagaStep step : steps) {
                // 执行正向操作
                step.execute();
                // 记录已执行步骤
                executedSteps.add(step);
            }
            // 标记为已完成
            status = SagaStatus.COMPLETED;
        } catch (Exception e) {
            // 标记为失败
            status = SagaStatus.FAILED;
            // 执行补偿
            compensate();
            throw new SagaException("Saga execution failed", e);
        }
    }

    /**
     * 补偿操作
     * 按相反顺序执行已执行步骤的补偿操作
     */
    public void compensate() {
        // 反转执行顺序
        Collections.reverse(executedSteps);
        for (SagaStep step : executedSteps) {
            try {
                // 执行补偿操作
                step.compensate();
            } catch (Exception e) {
                // 记录日志，继续补偿其他步骤
                System.err.println("Compensation failed for step " + step.getStepName() + ": " + e.getMessage());
            }
        }
        // 标记为已补偿
        status = SagaStatus.COMPENSATED;
    }

    public SagaStatus getStatus() {
        return status;
    }

}
